#include "XGraphicsSubsystem.h"
#include "gui/iGraphicsSubsystem.h"
#include "XGLWindow.h"
#include "XEventListener.h"
#include "XWindowImpl.h"
#include "render/GLRenderer.h"
#include "core/io/IOStream.h"
#include "gui/EventDispatcher.h"
#include "gui/EventManager.h"
#include "core/iException.h"
//#include "logger.h"

#include <string>
using std::string;

#include <map>
using std::map;

#include <X11/Xlib.h>

using namespace neiderra::core;
using namespace neiderra::gui;
 using namespace neiderra::rendering;
//using namespace neiderra::core::io;

int xIOErrorHandler(Display* d)
{
	char *buf;
	int l = 100;
// 	Core::defLogger->log("X IO error");
}

int xErrorHandler(Display* d, XErrorEvent* e)
{
	char *buf;
	int l = 100;
	XGetErrorText(d,e->error_code,buf,l);
	
// 	Core::defLogger->log(buf);
}

XGraphicsSubsystem::XGraphicsSubsystem(Core* core): iGraphicsSubsystem(core)
{
	_display = XOpenDisplay(0);
	_eventListener = new XEventListener(core, _display);
	_eventManager = new EventManager(core);
	_eventDispatcher = new EventDispatcher(core);
	
 	_renderer = new glRenderer(core);

	XSetErrorHandler(&xErrorHandler);
}

XGraphicsSubsystem::~XGraphicsSubsystem()
{
	map<Window, GUIWindow*>::iterator i = _windows.begin();
	
	for(;i!=_windows.end();i++)
	{
		if(i->second != 0)
		{
			GUIWindow* win = i->second;
			delete win;
		}
	}
	
	delete _eventListener;
	delete _eventDispatcher;
	delete _eventManager;
	delete _renderer; 
			
	XCloseDisplay(_display);
}

Display* XGraphicsSubsystem::GetDisplay()
{
	return _display;
}

GUIWindow* XGraphicsSubsystem::createSystemWindow( const string& title )
{
	XGLWindow * window = new XGLWindow(core, title, 100, 100, 400, 300);
	XWindowImpl* impl = dynamic_cast<XWindowImpl*>(window->getWindowImpl());

	if(impl)
	  _windows[((XWindowImpl*)(window->getWindowImpl()))->GetXID()] = window;
	return window;
}

void XGraphicsSubsystem::makeCurrentWindow( GUIWindow* a )
{
  // fixme: makeCurrentWindow is not implemented
// 	_renderer->init( a->getWindowImpl() );
  throw ENotImplemented("XGraphicsSubsystem::makeCurrentWindow");
}

void XGraphicsSubsystem::update(double time)
{
	_eventListener->listen();
	_eventDispatcher->dispatchEvents();
 	_renderer->update(time);
}

GUIWindow* XGraphicsSubsystem::GetWindowPointer( Window w )
{
	return _windows[w];
}
